package com.eastfair.auth.controller;

import cn.hutool.core.collection.CollectionUtil;
import com.eastfair.auth.dao.BusinessMapper;
import com.eastfair.auth.dto.*;
import com.eastfair.auth.entity.UserOrganization;
import com.eastfair.auth.service.OrganizationService;
import com.eastfair.annotation.annotation.base.BaseControllerInfo;
import com.eastfair.annotation.annotation.log.SysLog;
import com.eastfair.auth.entity.Organization;

import java.util.*;
import java.util.stream.Collectors;

import com.eastfair.auth.service.UserOrganizationService;
import com.eastfair.auth.vo.OrganizationVo;
import com.eastfair.boot.controller.SuperController;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.eastfair.cache.redis.RedisOps;
import com.eastfair.demand.auth.OrganizationVoGroupClass;
import com.eastfair.echo.core.EchoService;
import com.eastfair.core.base.R;
import com.eastfair.log.point.PointUtil;
import com.eastfair.vo.VoGroupClass;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


/**
 * <p>
 * 前端控制器
 *
 * </p>
 *
 * @author ligang
 * @date 2021-07-16
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/organization")
@Api(value = "Organization", tags = "组织")
public class OrganizationController extends SuperController<OrganizationService, Long, Organization, OrganizationPageQuery, OrganizationSaveDTO, OrganizationUpdateDTO> {

    @Autowired
    private EchoService echoService;

    @Autowired
    private RedisOps redisOps;

    @Autowired
    BusinessMapper businessMapper;

    @Autowired
    PointUtil pointUtil;

    @Autowired
    UserOrganizationService userOrganizationService;

    @Override
    public void handlerResult(IPage<Organization> page) {
        // 想让返回值实现自动回显，请将此行代码打开
        // echoService.action(page);
    }

    /**
     * Excel导入后的操作
     *
     * @param list
     */
    @Override
    public R<Boolean> handlerImport(List<Map<String, String>> list) {
        List<Organization> organizationList = list.stream().map((map) -> {
            Organization organization = Organization.builder().build();
            //TODO 请在这里完成转换
            return organization;
        }).collect(Collectors.toList());

        return R.success(baseService.saveBatch(organizationList));
    }


    /**
     * 删除
     *
     * @param organizationDTO 组织实体DTO
     * @return
     */
    @ApiOperation(value = "删除", notes = "删除")
    @PostMapping("/del")
    @SysLog("删除")
    public R del(@RequestBody OrganizationDTO organizationDTO) {
        return baseService.del(organizationDTO.getOrgId());
    }


    /**
     * 删除(前端用)
     *
     * @param ids 组织实体DTO
     * @return
     */
    @ApiOperation(value = "删除", notes = "删除")
    @DeleteMapping("/delToLead")
    @SysLog("删除(前端用)")
    public R delToLead(@RequestBody List<Long> ids) {
        if (ids != null && !ids.isEmpty()) {
            for (Long id : ids) {
                baseService.del(id);
            }
        }
        return R.success();
    }


//    /**
//     * 查询节点全部子信息
//     * @param orgId 组织id
//     * @return
//     */
//    @ApiOperation(value = "查询节点全部信息", notes = "查询主办全部子信息")
//    @GetMapping("/findAllById")
//    @ApiVersion("v7.0.1")
//    @BaseControllerInfo(voGroup = {VoGroupClass.findAllOrganization.class})
//    public R<OrganizationVo> findAllOfHostByV701(Long orgId) {
//        log.info("执行版本：v7.0.1");
//        OrganizationVo organizationVo = baseService.findAllById(orgId);
//        return R.success(organizationVo);
//    }

    /**
     * 查询节点的所有的菜单和功能
     *
     * @param orgId 组织id
     * @return
     */
    @ApiOperation(value = "查询节点的所有的菜单和功能", notes = "查询节点的所有的菜单和功能")
    @GetMapping("/findMenuOrFunctionById")
    @BaseControllerInfo(voGroup = {OrganizationVoGroupClass.findMenuOrFunctionById.class})
    @SysLog("查询节点的所有的菜单和功能")
    public R<OrganizationVo> findMenuOrFunctionById(Long orgId) {
        log.info("执行版本：v6.0.1");
        OrganizationVo organizationVo = baseService.findMenuOrFunctionById(orgId);
        return R.success(organizationVo);

    }

    /**
     * 查询节点全部子信息
     *
     * @param orgId 组织id
     * @return
     */
    @ApiOperation(value = "查询节点全部信息", notes = "查询主办全部子信息")
    @GetMapping("/findAllById")
    @BaseControllerInfo(voGroup = {OrganizationVoGroupClass.findAllOrganization.class})
    @SysLog("查询节点全部信息")
    public R<OrganizationVo> findAllOfHost(Long orgId) {
        OrganizationVo organizationVo = baseService.findAllById(orgId);
//        BusinLoadUserPermissPoint businLoadUserPermissPoint = new BusinLoadUserPermissPoint();
//        businLoadUserPermissPoint.setUserIdList(Arrays.asList(ContextUtil.getUserId()));
//        businLoadUserPermissPoint.setProjectId(ContextUtil.getProjectId());
//        pointUtil.addBusinPointMsg(businLoadUserPermissPoint);


//        SpringUtils.publishEvent(UserLoginPoint.builder().email("数据3").msg("操作记录1").build());

        return R.success(organizationVo);


    }

    /**
     * 创建节点组     * @return
     *
     * @param organizationDTO 组织实体
     */
    @ApiOperation(value = "创建节点组", notes = "创建节点组")
    @PostMapping("/createOrgGroup")
    @SysLog("创建节点组")
    public R createOrgGroup(@RequestBody @Validated({OrganizationDTO.VerifyCreateOrgGroup.class}) OrganizationDTO organizationDTO) {
        return baseService.createOrg(organizationDTO);
    }

    /**
     * 修改节点
     *
     * @param organizationDTO 修改节点
     * @return
     */
    @ApiOperation(value = "修改节点", notes = "修改节点")
    @PostMapping("/updOrgGroup")
    @SysLog("修改节点")
    public R updOrgGroup(@RequestBody @Validated({OrganizationDTO.VerifyUpdOrgGroup.class}) OrganizationDTO organizationDTO) {
        return baseService.updOrg(organizationDTO);
    }

    /**
     * 修改节点(前端用)
     *
     * @param organizationDTO 修改节点
     * @return
     */
    @ApiOperation(value = "修改节点", notes = "修改节点")
    @PutMapping("/updOrgGroupToLead")
    @SysLog("修改节点")
    public R updOrgGroupToLead(@RequestBody @Validated({OrganizationDTO.VerifyUpdOrgGroup.class}) OrganizationDTO organizationDTO) {
        return baseService.updOrg(organizationDTO);
    }

    /**
     * 修改
     *
     * @param organizationUpdateDTO 组织更新实体
     * @return
     */
    @ApiOperation(value = "修改", notes = "修改")
    @PostMapping("/updMenu")
    @SysLog("修改")
    public R updMenu(@RequestBody OrganizationUpdateDTO organizationUpdateDTO) {
        Organization organization = new Organization();
        BeanUtils.copyProperties(organizationUpdateDTO, organization);
        return R.success(baseService.updateById(organization));
    }


    /**
     * 置顶
     *
     * @param id 组织id
     * @return
     */
    @ApiOperation(value = "置顶", notes = "置顶")
    @SysLog("置顶")
    @PostMapping("/sortTop")
    public R sortTop(@RequestBody Long id) {
        baseService.sortTop(id);
        return R.success();
    }


    /**
     * 添加组织关联角色
     *
     * @param orgRoleDto 组织角色实体
     * @return
     */
    @ApiOperation(value = "添加组织关联角色", notes = "添加组织关联角色")
    @PostMapping("/addOrgRole")
    @SysLog("添加组织关联角色")
    public R addOrgRole(@RequestBody OrganizationRoleDto orgRoleDto) {
//        return baseService.addOrgRole(orgRoleDto.getOrgId(), orgRoleDto.getRoleIds(), orgRoleDto.isConduction());
        return baseService.addOrgRole(orgRoleDto.getOrganizationId(), orgRoleDto.getRoleIds(), orgRoleDto.isConduction());
    }


    /**
     * 更新组织关联角色
     *
     * @param orgRoleDto 组织角色实体
     * @return
     */
    @ApiOperation(value = "更新组织关联角色", notes = "更新组织关联角色")
    @PostMapping("/updOrgRole")
    @SysLog("更新组织关联角色")
    public R updOrgRole(@RequestBody OrganizationRoleDto orgRoleDto) {
        return baseService.updOrgRole(orgRoleDto.getOrganizationId(), orgRoleDto.getRoleIds(), orgRoleDto.isConduction());
    }


    /**
     * 剔除菜单关联角色
     *
     * @param orgRoleDto 组织角色实体
     * @return
     */
    @ApiOperation(value = "剔除菜单关联角色", notes = "剔除菜单关联角色")
    @PostMapping("/removeOrgRole")
    @SysLog("剔除菜单关联角色")
    public R removeOrgRole(@RequestBody OrganizationRoleDto orgRoleDto) {
        return baseService.removeOrgRole(orgRoleDto.getOrganizationId(), orgRoleDto.getRoleIds(), orgRoleDto.isConduction());
    }

    /**
     * 剔除关联的角色
     *
     * @param roleIds 角色id集合
     * @return
     */
    @ApiOperation(value = "剔除关联的角色", notes = "剔除关联的角色")
    @PostMapping("/removeOfRole")
    @SysLog("剔除关联的角色")
    public R removeOfRole(@RequestBody List<Long> roleIds) {
        return baseService.removeOfRole(roleIds);
    }


    /**
     * 通过资源查询角色Id集合
     *
     * @param resourceId 资源id
     * @return
     */
    @ApiOperation(value = "通过资源查询角色Id集合", notes = "通过资源查询角色Id集合")
    @GetMapping("/queryRoleOfResourceId")
    @SysLog("通过资源查询角色Id集合")
    public R<List<Long>> queryRoleOfResourceId(@RequestParam("resourceId") Long resourceId) {
        return R.success(baseService.queryRoleOfResourceId(resourceId));
    }


    /**
     * 查询资源指定节点下的组织Id集合
     *
     * @param resourceId 资源id
     * @return
     */
    @ApiOperation(value = "查询资源指定节点下的组织Id集合", notes = "查询资源指定节点下的组织Id集合")
    @GetMapping("/queryRoleOfOrgId")
    @SysLog("查询资源指定节点下的组织Id集合")
    public R<List<Long>> queryOrgOfResourceId(@RequestParam("resourceId") Long resourceId, @RequestParam("orgId") Long orgId) {
        return R.success(baseService.queryOrgOfResourceId(resourceId, orgId));
    }


    /**
     * 查询 项目下的类型节点信息
     *
     * @param organizationDTO
     * @return
     */
    @ApiOperation(value = "查询资源指定节点下的组织Id集合", notes = "查询资源指定节点下的组织Id集合")
    @PostMapping("/queryOrgOfType")
    @SysLog("查询资源指定节点下的组织Id集合")
    public R<Organization> queryOrgOfType(@RequestBody OrganizationDTO organizationDTO) {
        return R.success(baseService.queryOrgOfType(organizationDTO.getOrgType(), null));
    }


    /**
     * 通过类型查询所在的组织，并查询旗下所有子节点
     *
     * @param organizationDTO 组织id
     * @return
     */
    @ApiOperation(value = "通过类型查询所在的组织", notes = "通过类型查询所在的组织")
    @PostMapping("/findAllOfOrgOfType")
    @BaseControllerInfo(voGroup = {OrganizationVoGroupClass.findAllOrganization.class})
    @SysLog("通过资源查询所在的组织")
    public R<OrganizationVo> findAllOfOrgOfType(@RequestBody OrganizationDTO organizationDTO) {
        Organization organization = baseService.queryOrgOfType(organizationDTO.getOrgType(), null);
        if (organization != null) {
            OrganizationVo organizationVo = baseService.findAllById(organization.getId());
            return R.success(organizationVo);
        }
        return R.success(null);
    }


    /**
     * 通过类型查询所在的组织（集合，前端用），并查询旗下所有子节点
     *
     * @param organizationDTO 组织id
     * @return
     */
    @ApiOperation(value = "通过类型查询所在的组织（集合，前端用）", notes = "通过类型查询所在的组织（集合，前端用）")
    @PostMapping("/findAllOrgOfTypeToLead")
    @BaseControllerInfo(voGroup = {OrganizationVoGroupClass.findAllOrganization.class})
    @SysLog("通过资源查询所在的组织")
    public R<List<OrganizationVo>> findAllOrgOfTypeToLead(@RequestBody OrganizationDTO organizationDTO) {
        Organization organization = baseService.queryOrgOfType(organizationDTO.getOrgType(), organizationDTO.getParentId());
        if (organization != null) {
            OrganizationVo organizationVo = baseService.findAllByIdNoResource(organization.getId());
            return R.success(Arrays.asList(organizationVo));
        }
        return R.success(null);
    }


    /**
     * 查询资源所在的指定组织里的信息
     *
     * @param orgIds 组织id
     * @return
     */
    @ApiOperation(value = "查询资源所在的指定组织里的信息", notes = "查询资源所在的指定组织里的信息")
    @GetMapping("/queryOrgOfResource")
    @SysLog("查询资源所在的指定组织里的信息")
    public R<Map<Long, List<Organization>>> queryOrgVoOfResourceId(@RequestParam("resourceIds") List<Long> resourceIds, @RequestParam("orgIds") List<Long> orgIds) {
        return R.success(baseService.queryOrgVoOfResourceId(resourceIds, orgIds));
    }


    /**
     * 查询详情
     *
     * @param id 组织id
     * @return
     */
    @ApiOperation(value = "查询详情", notes = "查询详情")
    @GetMapping("/queryById/{id}")
    @SysLog("查询详情")
    @BaseControllerInfo(voGroup = {VoGroupClass.findAllOrganization.class})
    public R<OrganizationVo> queryById(@PathVariable("id") Long id) {
        return R.success(baseService.findAllById(id));
    }


    /**
     * 查询用户权限信息，用于接口判断
     *
     * @param userIds
     * @return
     */
    @ApiOperation(value = "查询用户权限信息", notes = "查询用户权限信息")
    @GetMapping("/loadUserPermission")
    @SysLog("查询用户权限信息")
    public R<List<Map>> loadUserPermission(@RequestParam("userIds") List<Long> userIds) {
        return R.success(baseService.loadUserPermission(userIds));
    }


    /**
     * 根据组织查询用户的权限信息，用于接口判断
     *
     * @param orgIds
     * @return
     */
    @ApiOperation(value = "根据组织查询用户的权限信息", notes = "查询用户权限信息")
    @GetMapping("/loadUserPermissionOfOrg")
    @SysLog("根据组织查询用户的权限信息")
    public R<List<Map>> loadUserPermissionOfOrg(@RequestParam("orgIds") List<Long> orgIds) {
        return R.success(baseService.loadUserPermissionOfOrg(orgIds));
    }

    /**
     * 根据角色查组织进而查询用户的权限信息，用于接口判断
     *
     * @param roleIds
     * @return
     */
    @ApiOperation(value = "根据角色查组织进而查询用户的权限信息", notes = "根据角色查组织进而查询用户的权限信息")
    @GetMapping("/loadUserPermissionOfRole")
    @SysLog("根据角色查组织进而查询用户的权限信息")
    public R<List<Map>> loadUserPermissionOfRole(@RequestParam("roleIds") List<Long> roleIds) {
        return R.success(baseService.loadUserPermissionOfRole(roleIds));
    }


    /**
     * 通过用户查询菜单id
     *
     * @param userId
     * @return
     */
    @ApiOperation(value = "通过用户查询菜单id", notes = "通过用户查询菜单id")
    @GetMapping("/queryMenuIdOfUser")
    @SysLog("通过用户查询菜单id")
    public R<List<Long>> queryMenuIdOfUser(@RequestParam("userId") Long userId) {
        return R.success(baseService.queryMenuIdOfUser(userId));
    }


    /**
     * 查询id集合
     *
     * @param ids
     * @return
     */
    @ApiOperation(value = "查询id集合", notes = "查询id集合")
    @GetMapping("/queryList")
    @SysLog("查询id集合")
    public R<List<OrganizationVo>> queryList(@RequestParam("ids") List<Long> ids) {
        return R.success(baseService.doToVos(baseService.listOfOrganization(null, ids)));
    }

    /**
     * 添加用户到组织
     *
     * @param organizationDTO 组织实体
     * @return
     */
    @ApiOperation(value = "添加用户到组织", notes = "添加用户到组织")
    @PostMapping("/trasactionTest")
    @SysLog("添加用户到组织")
    public R trasactionTest(@RequestBody OrganizationDTO organizationDTO) {
        Organization organization = new Organization();
        BeanUtils.copyProperties(organizationDTO, organization);
        return R.success(baseService.save(organization));
    }


    /**
     * 查询用户所在的组织
     *
     * @param organizationDTO
     * @return
     */
    @ApiOperation(value = "查询用户所在的组织", notes = "查询用户所在的组织")
    @PostMapping("/queryOrgOfUserId")
    @SysLog("查询用户所在的组织")
    public R<Map<Long, List<OrganizationVo>>> queryOrgOfUserId(@RequestBody OrganizationDTO organizationDTO) {
        Map<Long, List<OrganizationVo>> result = new HashMap<>();
        List<UserOrganization> userOrganizationList = userOrganizationService.listOfUserOrganization(null, organizationDTO.getUserIds(), null);
        if (CollectionUtil.isEmpty(userOrganizationList)) {
            return R.success(null);
        }
        List<Long> orgIds = userOrganizationList.stream().map(UserOrganization::getOrganizationId).collect(Collectors.toList());

        List<OrganizationVo> organizationVoList = baseService.doToVos(baseService.listOfOrganization(null, orgIds));
        Map<Long, List<UserOrganization>> map = userOrganizationList.stream().collect(Collectors.groupingBy(s -> s.getUserId()));
        for (Long userId : map.keySet()) {
            List<UserOrganization> userOrganizationList1 = map.get(userId);
            for (UserOrganization userOrganization : userOrganizationList1) {
                result.put(userId, organizationVoList.stream().filter(s -> s.getId().equals(userOrganization.getOrganizationId())).collect(Collectors.toList()));
            }
        }
        return R.success(result);
    }


    /**
     * 查询子组织id
     *
     * @param organizationDTO
     * @return
     */
    @ApiOperation(value = "查询子组织id", notes = "查询子组织id")
    @PostMapping("/queryChildOrgIdOfOrgId")
    @SysLog("查询子组织id")
    public R<List<Long>> queryChildOrgIdOfOrgId(@RequestBody OrganizationDTO organizationDTO) {
        List<Long> orgIds = baseService.queryOrgChildId(Arrays.asList(organizationDTO.getOrgId()));
        return R.success(orgIds);
    }
}
